package cn.wolfcode.wolf2world.redis.service.impl;

import cn.wolfcode.wolf2world.domain.UserInfo;
import cn.wolfcode.wolf2world.domain.UserStrategyFavoer;
import cn.wolfcode.wolf2world.exception.LogicException;
import cn.wolfcode.wolf2world.myenum.RedisKeysEnum;
import cn.wolfcode.wolf2world.redis.service.StaticRedisService;
import cn.wolfcode.wolf2world.redis.service.UserRedisService;
import cn.wolfcode.wolf2world.service.UserStrategyFavoerService;
import cn.wolfcode.wolf2world.utils.DateUtil;
import cn.wolfcode.wolf2world.utils.ParamMap;
import cn.wolfcode.wolf2world.vo.StaticRedisVO;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.time.Duration;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author 杨兴健
 * @Date 2020/8/7 21:12
 */
@Service
@Slf4j
public class UserRedisServiceImpl implements UserRedisService {

    @Value("${trip.hponemessage.url}")
    private String url;
    @Value("${trip.phonemessage.appkey}")
    private String appkey;

    @Autowired
    private StringRedisTemplate redisTemplate;

    @Autowired
    private StaticRedisService staticRedisService;
    @Autowired
    private UserStrategyFavoerService userStrategyFavoerService;
    /**
     * 发送短信验证码
     * @param phone 手机号码
     */
    @Override
    public void sendVerifyCode(String phone) {
        //生成短信验证码
        String code = UUID.randomUUID().toString()
                .replace("-", "")
                .substring(0, 4);
        log.info("验证码生成成功:{}", code);
        //发送的信息
        String msg = new StringBuilder(100).append("【创信】你的验证码是：").append(code).append(",请尽快验证。验证码").append(RedisKeysEnum.VERIFY_CODE.getTime() / 60).append("分钟过期").toString();
        log.info("发送的信息:{}", msg);
        log.info("url:{},appkey:{}",url,appkey);
        //发送短信验证码
        //url:https://way.jd.com/chuangxin/dxjk?mobile=13568813957&content=【创信】你的验证码是：5873，3分钟内有效！&appkey=29d24d89cfd893a44020ca0401ea6467
        RestTemplate restTemplate = new RestTemplate();
        String str = restTemplate.getForObject(url, String.class, phone, msg, appkey);
        log.info("短信网关返回的信息{}", str);
        if (!str.contains("Success")) {
            log.error("短信发送失败，这里假装成功");
//            throw new LogicException("短信发送失败");
        }
        log.info("短信发送成功");
        //保存短信验证码再redis,设置过期时间为2分钟
        String codeKey = RedisKeysEnum.VERIFY_CODE.join(phone);
        redisTemplate.opsForValue().set(codeKey, code, Duration.ofSeconds(RedisKeysEnum.VERIFY_CODE.getTime()));
        log.info("验证码保存到redis数据库成功");
    }

    /**
     * 校验验证码是否正确
     * @param phone      手机号码
     * @param verifyCode 用户发过来的验证码
     */
    @Override
    public void checkCode(String phone, String verifyCode) {
        log.info("校验手机号:{}的验证码:{}是否正确", phone, verifyCode);
        String codeKey = RedisKeysEnum.VERIFY_CODE.join(phone);
        String code = redisTemplate.opsForValue().get(codeKey);
        if (!Objects.equals(verifyCode, code)) {
            log.error("验证码不正确");
            throw new LogicException("验证码不正确");
        }
        log.info("验证码正确");
    }

    /**
     * 保存当前用户在redis中
     *
     * @param user 当前用户对象
     * @return token
     */
    @Override
    public String saveUser(UserInfo user) {
        log.info("保存当前登录用户到redis");
        //定义key user_toke:uuid
        //生成一个uuid
        String token = UUID.randomUUID().toString().replace("-", "");
        log.info("生成token:{}", token);
        //拼接key
        String key = RedisKeysEnum.USER_TOKEN.join(token);
        //user转换成json对象
        //保存在redis,设置过期时间30分钟
        redisTemplate.opsForValue().set(key, JSON.toJSONString(user), Duration.ofSeconds(RedisKeysEnum.USER_TOKEN.getTime()));
        log.info("保存成功");
        return token;
    }

    /**
     * 根据token获取当前登录用户,并刷新当前用户登录的有效时间
     *
     * @param token
     * @return
     */
    @Override
    public UserInfo getCurrentUser(String token) {
        log.info("根据token:{},获取当前登录用户", token);
        //判断token是否为空
        if (!StringUtils.hasLength(token)) {
            log.error("token为空");
            return null;
        }
        //拼接key
        String key = RedisKeysEnum.USER_TOKEN.join(token);

        //获取userinfo
        String userinfo = redisTemplate.opsForValue().get(key);
        if (!StringUtils.hasLength(userinfo)) {
            log.error("token不存在，或者已过期");
            return null;
        }

        //刷新登录过期时间(30分钟)
        redisTemplate.expire(key, RedisKeysEnum.USER_TOKEN.getTime(), TimeUnit.SECONDS);
        log.info("获取当前登录用户成功,刷新登录过期时间30分钟");
        //把json对象转换成user对象并返回
        return JSON.parseObject(userinfo, UserInfo.class);
    }

    /**
     * 是否存在用户攻略收藏key
     * @param id
     * @return
     */
    @Override
    public Boolean hasKey(String id) {
        //拼接key
        String key = RedisKeysEnum.USER_STRATEGY_FAVOR.join(id);
        return redisTemplate.hasKey(key);
    }

    /**
     * 设置用户收藏攻略
     * @param userStrategyFavoer
     */
    @Override
    public void setUserStrategyFavor(UserStrategyFavoer userStrategyFavoer) {
        //拼接key
        String key = RedisKeysEnum.USER_STRATEGY_FAVOR.join(userStrategyFavoer.getUid());
        //设置
        redisTemplate.opsForValue().set(key,JSON.toJSONString(userStrategyFavoer));
    }

    /**
     * 点击收藏
     * @param sid
     * @return true：收藏，false：取消收藏
     */
    @Override
    public boolean clickFavor(String uid,String sid) {

        //获取攻略统计数据vo
        StaticRedisVO vo = staticRedisService.getStaticRedisVO(sid);
        //获取用户的攻略收藏对象
        UserStrategyFavoer usf = this.getUserStrategyFavor(uid);

        List<String> list = usf.getSid();

        if (list.contains(sid)) {
            //存在，取消收藏 攻略收藏-1
            vo.setFavornum(vo.getFavornum() - 1);
            //移除集合中的sid
            list.remove(sid);
        }else {
            //集合为空或sid不存在，收藏操作 ，攻略+1
            vo.setFavornum(vo.getFavornum() + 1);
            //添加进集合
            list.add(sid);
        }
        //保存vo
        staticRedisService.setStaticRedisVO(vo);
        //保存UserStrategyFavor对象
        this.setUserStrategyFavor(usf);
        return list.contains(sid);
    }

    /**
     * 获取用户的收藏对象
     * @param uid
     * @return
     */
    @Override
    public UserStrategyFavoer getUserStrategyFavor(String uid) {
        //拼接key
        String key = RedisKeysEnum.USER_STRATEGY_FAVOR.join(uid);
        //判断key是否存在
       if (this.hasKey(uid)) {
            //存在，redis中获取数据
            String value = redisTemplate.opsForValue().get(key);
            return JSON.parseObject(value, UserStrategyFavoer.class);
        }else {
            //不存在，数据库中获取
            UserStrategyFavoer usf = userStrategyFavoerService.findbyUid(uid);
            if (usf == null) {
                usf = new UserStrategyFavoer();
                usf.setUid(uid);
                usf.setSid(new ArrayList<>());
            }
            return usf;
        }

    }


    /**
     * 获取所有用户收藏攻略
     * @return
     */
    @Override
    public List<UserStrategyFavoer> getUserStrategyFaverList() {
        //拼接key
        String key = RedisKeysEnum.USER_STRATEGY_FAVOR.join("*");
        //获取所有匹配的key
        Set<String> keys = redisTemplate.keys(key);
        List<UserStrategyFavoer> list = new ArrayList<>();
        //遍历封装成UersStrategyFavoer对象
        for (String k: keys) {
            String value = redisTemplate.opsForValue().get(k);
            UserStrategyFavoer usf = JSON.parseObject(value, UserStrategyFavoer.class);
            list.add(usf);
        }
        return list;
    }

    /**
     * 统计窝的访问数
     * @param id
     * @param did
     * @return
     */
    @Override
    public Map statcview(String id, String did) {
        //拼接累计key
        String totalKey = RedisKeysEnum.MYWO_TOTAL.join(id);
        //拼接今天key
        String todayKey = RedisKeysEnum.MYWO_TODAY.join(id);

        //如果不存在key，生成key
        redisTemplate.opsForValue().setIfAbsent(totalKey, "0");
        redisTemplate.opsForValue().setIfAbsent(todayKey, "0",Duration.ofSeconds(DateUtil.getSurplusTime()));

        ParamMap map = ParamMap.newInstance();
        //判断是否是当前用户
        if(Objects.equals(id,did)) {
            //是,获取累计数和今天累计
            //获取key的值
            String total = redisTemplate.opsForValue().get(totalKey);
            String today = redisTemplate.opsForValue().get(todayKey);
            map.put("totalView",total).put("todayView",today);
        }else {
            //不是当前用户
            Long total = redisTemplate.opsForValue().increment(totalKey);
            Long today = redisTemplate.opsForValue().increment(todayKey);
            map.put("totalView",total).put("todayView",today);
        }
        return map;
    }

}
